package com.taotao.controller;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import com.taotao.common.pojo.BaseResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.taotao.common.enums.OperateType;
import com.taotao.common.enums.TemplateDesc;
import com.taotao.common.utils.Constants;
import com.taotao.common.utils.RedisUtils;
import com.taotao.mapper.EyMemberMapper;
import com.taotao.pojo.EyMember;
import com.taotao.service.ChargeService;
import com.taotao.service.MemberService;
import com.taotao.service.MessageInfoService;
import com.taotao.service.OperateLogService;
import com.taotao.service.OrderService;
import com.taotao.service.ParamService;
import com.taotao.service.WechatService;
 
@ServerEndpoint(value="/api/socket/{socketId}")
@Component
public class ApiSocketController {

	private static ConcurrentHashMap<String, ApiSocketController> webSocketMap = new ConcurrentHashMap<String, ApiSocketController>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    public Session WebSocketsession;
    public String socketId;

	BaseResult baseResult = new BaseResult();
    
    public static MessageInfoService messageInfoService;
    public static MemberService memberService;
    public static ChargeService chargeService;
    public static EyMemberMapper eyMemberMapper;
    public static OperateLogService operateLogService;
    public static WechatService wechatService;
    public static ParamService paramService;
    public static OrderService orderService;
    
    public static void init(){
    	messageInfoService = SpringContext.getBean(MessageInfoService.class);
    	memberService = SpringContext.getBean(MemberService.class);
    	eyMemberMapper = SpringContext.getBean(EyMemberMapper.class);
    	operateLogService = SpringContext.getBean(OperateLogService.class);
    	wechatService = SpringContext.getBean(WechatService.class);
    	paramService = SpringContext.getBean(ParamService.class);
    	chargeService = SpringContext.getBean(ChargeService.class);
    	orderService = SpringContext.getBean(OrderService.class);
    }

	/**
	 * @param socketId
	 * @param WebSocketsession
	 * @param config
	 */
	@OnOpen
    public void onOpen(@PathParam(value = "socketId") String socketId,
    		Session WebSocketsession, EndpointConfig config) {
    	try {
            this.socketId = socketId;
            this.WebSocketsession = WebSocketsession;
            if(webSocketMap.get(socketId)==null){
            	webSocketMap.put(socketId, this);//加入map中
            	
            	List<String> socketIdList= RedisUtils.lrange(Constants.onLineScoketId);
            	boolean exist=false;
            	for(String id:socketIdList){
            		if(socketId.endsWith(id)){
            			exist=true;
            			break;
            		}
            	}
            	if(!exist){
            		RedisUtils.lpush(Constants.onLineScoketId, socketId); //加入到redis中去
            	}
            	
            	Integer memberId=Integer.parseInt(socketId.split("_")[1]);
            	if(operateLogService==null){
                 	ApiSocketController.init();
                }
            	operateLogService.insert(memberId, null,null,OperateType.operateType_20.getDesc(),OperateType.operateType_20.getCode(),""); 
            	
            	List<String> msgList= RedisUtils.lrange(Constants.offLineMsg);
            	
            	for(String msg:msgList){
            		JSONObject msgJson = (JSONObject) JSONObject.parse(msg);
            		String receiver = String.valueOf(msgJson.get("receiver"));
            		String resultCode = String.valueOf(msgJson.get("resultCode"));
            	   	String receiver_socketId=Constants.socketId_prefix+"_"+receiver;
            	   	if(receiver_socketId.equals(this.socketId)){
            	   		System.out.println("发送离线的消息提醒");
            	   		webSocketMap.get(this.socketId).sendMessage(msg);
            	   		RedisUtils.lrem(Constants.offLineMsg, msg);
            	   		if("-2".equals(resultCode)){
            	   			operateLogService.insert(memberId, null,null,OperateType.operateType_27.getDesc(),OperateType.operateType_27.getCode(),""); 
            	   		}else{
            	   			operateLogService.insert(memberId, null,null,OperateType.operateType_28.getDesc(),OperateType.operateType_28.getCode(),""); 
            	   		}
            	   		
            	   	}
            	}
            	
            	System.out.println("有新连接加入！在线人数为：" + webSocketMap.size());
                for(String key:webSocketMap.keySet()){
                	System.out.println("当前在线人："+key);
                }
            }
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
 
    
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (!this.socketId.equals("")) {
        	webSocketMap.remove(this.socketId);  //从set中删除
        	RedisUtils.lrem(Constants.onLineScoketId, this.socketId); //从Redis中删除离线的socketId
        	Integer memberId=Integer.parseInt(socketId.split("_")[1]);
        	if(operateLogService==null){
             	ApiSocketController.init();
            }
        	operateLogService.insert(memberId, null,null,OperateType.operateType_21.getDesc(),OperateType.operateType_21.getCode(),""); 
        	
            System.out.println("客户端关闭！当前在线人数为" + webSocketMap.size());
            for(String key:webSocketMap.keySet()){
            	System.out.println("当前在线人："+key);
            }
        }
    }

	/**
	 *
	 * @param webSocketsession
	 * @param e
	 */
	@OnError
    public void onError(Session webSocketsession, Throwable e) {
        System.out.println("发生错误关闭,当前在线人数：" + webSocketMap.size());
        for(String key:webSocketMap.keySet()){
        	System.out.println("当前在线人："+key);
        }
//        e.printStackTrace();
    }
    
 
    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @SuppressWarnings("unused")
	@OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("来自客户端的消息:" + message);
        //群发消息
        if (false) {
            sendAll(message);
        } else {
            //给指定的人发消息
            sendToUser(message);
        }
    }
    
    /**
     * 给指定的人发送消息
     * @param message
     */
    public Map<String, Object> sendToUser(String message) {
    	 JSONObject msgJson = (JSONObject) JSONObject.parse(message);
    	 try {
	    	if(wechatService==null){
	    		ApiSocketController.init();
	    	}
	    	String msgType = String.valueOf(msgJson.get("msgType"));
	    	String content = String.valueOf(msgJson.get("content"));
	    	String modeType = String.valueOf(msgJson.get("modeType"));
	    	String serviceName = String.valueOf(msgJson.get("serviceName"));
	    	String id = String.valueOf(msgJson.get("id"));
	    	String sessionKey = String.valueOf(msgJson.get("sessionKey"));
	    	String sender = String.valueOf(msgJson.get("sender"));
	    	String receiver = String.valueOf(msgJson.get("receiver"));
	    	String orderId = String.valueOf(msgJson.get("orderId"));
	    	String socketId_receiver=Constants.socketId_prefix+"_"+receiver;
	    	String socketId_sender=Constants.socketId_prefix+"_"+sender;
       
            if(!wechatService.msgCheck(content)){ //敏感信息，不发送
            	return baseResult.getErrorMap("Sensitive information in message");
            }
            
            EyMember senderMember = eyMemberMapper.selectByPrimaryKey(Integer.parseInt(sender));
            if("1".equals(senderMember.getIsBlack())){ //黑名单用户不发送
            	System.out.println("发送消息提醒");
				String msg="Send failure,please contact customer service";
            	msgJson.put("resultCode", "-1");
            	msgJson.put("resultMsg", msg);
             	webSocketMap.get(socketId_sender).sendMessage(msgJson.toJSONString());
				return baseResult.getErrorMap(msg);
            }
            
			if(Constants.num_1.equals(senderMember.getIsCharge())){ //开启付费模式
				if(chargeService==null){
                 	ApiSocketController.init();
                }
				Map<String,Object> resultMap=chargeService.chargeSubtract(senderMember,Constants.sendMessagePayMoney,"Send message");
				if("-3".equals(resultMap.get("resultCode"))){ //余额不足
					String msg="The balance is insufficient, please recharge it";
					msgJson.put("resultCode", "-3");
	            	msgJson.put("resultMsg", msg);
	             	webSocketMap.get(socketId_sender).sendMessage(msgJson.toJSONString());
					return baseResult.getErrorMap(msg);
				}
			}
            
    		if(messageInfoService==null){
	            	ApiSocketController.init();
	        }
            Map<String, Object> returnMap = messageInfoService.processMessage(sender,receiver,content,modeType,msgType,serviceName,id,true,sessionKey,orderId);//处理消息
            Map<String, String> data = (Map<String, String>) returnMap.get("data");
            sessionKey = data.get("sessionKey");
            sender = data.get("sender");
            String messageId = data.get("messageId");
            HashMap<String,String> onLineMap=new HashMap<String,String>();
			EyMember receiverMember = eyMemberMapper.selectByPrimaryKey(Integer.parseInt(receiver));
			if(StringUtils.isNotBlank(receiverMember.getSourceId())){ //给机器人的消息不用发
				return baseResult.getSuccMap();
			}
			
            String language = paramService.getParam("language");
            String nowTime="en".equals(language)? "just now ":"刚刚";
            
            msgJson.put("dateTime", nowTime);
            msgJson.put("sessionKey", sessionKey);
            
            if (webSocketMap.get(socketId_receiver) == null) {  //不在线
            	System.out.println("接受消息用户"+socketId_receiver+" 不在线，发送离线提醒");
            	//存redis,用户登录显示提醒图标
            	RedisUtils.lpush(Constants.offLineMsg, msgJson.toJSONString()); 
            	
            	//不在线，发送离线提醒
        	    HashMap<String,String> m=new HashMap<String,String>();
                m.put("sender", sender);
                m.put("receiver", receiver);
                m.put("sessionKey",sessionKey);
                m.put("messageId", messageId);
                m.put("content", content);
                m.put("templateId", TemplateDesc.Template_1.getCode()); //客户咨询提醒
                wechatService.sendMsg(m);
            }else{ //在线，发送消息
            	System.out.println("接受消息用户:"+socketId_receiver+" 在线，发送消息");
            	webSocketMap.get(socketId_receiver).sendMessage(msgJson.toJSONString());
				System.out.println("发送在线消息成功->"+msgJson.toJSONString());
            }
			 for(String key:webSocketMap.keySet()){
				 System.out.println("当前在线人："+key);
			 }
        } catch (Exception e) {
            e.printStackTrace();
        }
		return baseResult.getSuccMap();
    }
    /**
     * 给所有人发消息
     * @param message
     */
    public void sendAll(String message) {
        String now = getNowTime();
        for (String key : webSocketMap.keySet()) {
            try {
                if (!this.socketId.equals(key)) {
                	webSocketMap.get(key).sendMessage(now + "用户发来消息" + " <br/> " + message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    /**
     * 获取当前时间
     *
     * @return
     */
    public String getNowTime() {
        Date date = new Date();
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm");
        String time = format.format(date);
        return time;
    }
    
    
    /**
     * 这个方法与上面几个方法不一样。没有用注解，是根据自己需要添加的方法。
     *
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.WebSocketsession.getBasicRemote().sendText(message);
        //this.session.getAsyncRemote().sendText(message);
    }
    
}